using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Configuration;

/// <summary>
/// appsettings.json 映射器，提供强类型配置绑定和验证
/// </summary>
public class AppSettingsMapper
{
    private readonly IConfiguration _configuration;
    private readonly Dictionary<Type, object> _cachedConfigurations;
    private readonly object _lock = new();

    public AppSettingsMapper(IConfiguration configuration)
    {
        _configuration = configuration;
        _cachedConfigurations = new Dictionary<Type, object>();
    }

    /// <summary>
    /// 绑定配置到强类型对象并缓存
    /// </summary>
    /// <typeparam name="T">配置类型</typeparam>
    /// <param name="sectionName">配置节名称</param>
    /// <returns>配置对象</returns>
    public T Bind<T>(string sectionName) where T : class, new()
    {
        lock (_lock)
        {
            if (_cachedConfigurations.ContainsKey(typeof(T)))
            {
                return (T)_cachedConfigurations[typeof(T)];
            }

            var config = new T();
            var section = _configuration.GetSection(sectionName);
            
            if (section.Exists())
            {
                section.Bind(config);
                ValidateConfiguration(config);
            }

            _cachedConfigurations[typeof(T)] = config;
            return config;
        }
    }

    /// <summary>
    /// 绑定根级配置
    /// </summary>
    /// <typeparam name="T">配置类型</typeparam>
    /// <returns>配置对象</returns>
    public T BindRoot<T>() where T : class, new()
    {
        lock (_lock)
        {
            if (_cachedConfigurations.ContainsKey(typeof(T)))
            {
                return (T)_cachedConfigurations[typeof(T)];
            }

            var config = new T();
            _configuration.Bind(config);
            ValidateConfiguration(config);

            _cachedConfigurations[typeof(T)] = config;
            return config;
        }
    }

    /// <summary>
    /// 验证配置对象
    /// </summary>
    /// <param name="configuration">配置对象</param>
    private static void ValidateConfiguration(object configuration)
    {
        var validationContext = new ValidationContext(configuration);
        var validationResults = new List<ValidationResult>();
        
        if (!Validator.TryValidateObject(configuration, validationContext, validationResults, true))
        {
            var errors = string.Join(", ", validationResults.Select(r => r.ErrorMessage));
            throw new InvalidOperationException($"Configuration validation failed: {errors}");
        }
    }

    /// <summary>
    /// 清除缓存
    /// </summary>
    public void ClearCache()
    {
        lock (_lock)
        {
            _cachedConfigurations.Clear();
        }
    }

    /// <summary>
    /// 获取配置值并转换类型
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="key">配置键</param>
    /// <param name="defaultValue">默认值</param>
    /// <returns>配置值</returns>
    public T GetValue<T>(string key, T defaultValue = default!)
    {
        var value = _configuration.GetValue<T>(key, defaultValue);
        return value == null ? defaultValue : value;
    }

    /// <summary>
    /// 检查配置节是否存在
    /// </summary>
    /// <param name="sectionName">配置节名称</param>
    /// <returns>是否存在</returns>
    public bool SectionExists(string sectionName)
    {
        return _configuration.GetSection(sectionName).Exists();
    }
}
